﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using InkFx.WinControl.Core;
using InkFx.WinControl.Utils;
using DA = InkFx.WinControl.XIDEAlignment;
using DTGS = InkFx.WinControl.XIDETabGroupState;

namespace InkFx.WinControl
{
    [ToolboxItem(false)]
    public class XIDESplitControl : BaseSplitControl
    {
        public XIDESplitControl(XIDEPanel idePanel)
        {
            this.m_IDEPanel = idePanel;

            //SetStyle(Win32API.ControlStylesUAORSD, true);
            base.DoubleBuffered = true;
            base.SplitterWidth = 3;
            base.SplitterColor = Color.Transparent;
            base.Panel1MinSize = base.Panel2MinSize = 62;
            this.SplitterMoving += SplitControlSplitterMoving;
            this.SplitterMoved += SplitControlSplitterMoved;


            this.ParentChanged += IDESplitControlParentChanged;
            this.Panel1.ControlAdded += IDESplitControlPanelControlAdded;
            this.Panel2.ControlAdded += IDESplitControlPanelControlAdded;
            this.Panel1.ControlRemoved += IDESplitControlPanelControlRemoved;
            this.Panel2.ControlRemoved += IDESplitControlPanelControlRemoved;
        }


        private bool m_SizeInited = false;
        private void IDESplitControlParentChanged(object sender, EventArgs e)
        {
            var parent = (this.Disposing || this.IsDisposed) ? null : this.Parent;
            if (parent == null || parent.Disposing || parent.IsDisposed) return;
            if (parent is XIDEPanel) return;
            if (parent is InkFx.WinControl.SplitterPanel) return;
            if (parent is XIDEPanelCenter) return;

            throw new Exception(string.Format("IDESplitControl 只能是 IDEPanel 或者 SplitterPanel 或者 IDEPanelCenter 的子控件, 而不能是 类型为 '{0}' 的子控件!", parent.GetType().FullName));
        }
        private void IDESplitControlPanelControlAdded(object sender, ControlEventArgs e)
        {
            var ctrl = e.Control;
            if (!(ctrl is XIDETabGroup) && !(ctrl is XIDESplitControl) && !(ctrl is XIDEPanelCenter))
                throw new Exception(string.Format("IDESplitControl.Panel 的子控件, 只能是 IDETabGroup 或 IDESplitControl 或 IDEPanelCenter 类型, 而不能是 类型为 '{0}' 的子控件!", e.Control.GetType().FullName));

            if (m_SizeInited) return;

            var ctrls1 = this.Panel1.Controls;
            var ctrls2 = this.Panel2.Controls;
            if (ctrls1.Count != 1 || ctrls2.Count != 1) return;

            const int DEFAULT_SIZE = 200;
            bool center1 = this.IDEPanel.ContainsCenterPanel(this.Panel1);
            bool center2 = this.IDEPanel.ContainsCenterPanel(this.Panel2);
            if (center1 && !center2)
            {
                int minDistance = this.Panel1MinSize;
                base.FixedPanel = FixedPanel.Panel2;
                base.SplitterDistance = Math.Max(minDistance, (this.Orientation == Orientation.Horizontal ? this.Height : this.Width) - DEFAULT_SIZE);
            }
            else if (center2 && !center1)
            {
                int maxDistance = this.Width - this.Panel2MinSize;
                base.FixedPanel = FixedPanel.Panel1;
                base.SplitterDistance = Math.Min(maxDistance, DEFAULT_SIZE);
            }
            else
            {
                base.FixedPanel = FixedPanel.None;
                base.SplitterDistance = this.Orientation == Orientation.Horizontal ? (this.Height - this.SplitterWidth) / 2 : (this.Width - this.SplitterWidth) / 2;
            }

            m_SizeInited = true;
        }
        private void IDESplitControlPanelControlRemoved(object sender, ControlEventArgs e)
        {
            if (m_IDEPanel != null) m_IDEPanel.ResetLayout();
        }
        public bool IsSplitterMoving { get; private set; }

        private void SplitControlSplitterMoving(object sender, SplitterCancelEventArgs e)
        {
            IsSplitterMoving = true;
            SetCursor(this.Orientation != Orientation.Vertical ? Cursors.HSplit : Cursors.VSplit);
        }
        private void SplitControlSplitterMoved(object sender, SplitterEventArgs e)
        {
            IsSplitterMoving = false;
            SetCursor(null);
        }

        
        public static XIDESplitControl FindContainer(System.Windows.Forms.SplitterPanel panel)
        {
            if (panel == null || panel.Disposing || panel.IsDisposed) return null;
            var prop = typeof(InkFx.WinControl.SplitterPanel).GetProperty("Owner", Win32API.ReflectBindingFlags);
            return prop.GetValue(panel, null) as XIDESplitControl;
        }
        public static XIDESplitControl FindContainer(InkFx.WinControl.SplitterPanel panel)
        {
            if (panel == null || panel.Disposing || panel.IsDisposed) return null;
            return panel.Owner as XIDESplitControl;
        }


        private XIDEPanel m_IDEPanel;
        public XIDEPanel IDEPanel
        {
            get { return m_IDEPanel; }
        }
        public InkFx.WinControl.SplitterPanel ParentSplitPanel
        {
            get
            {
                var splitPanel = this.Parent as SplitterPanel;
                return splitPanel;
            }
        }
        public XIDESplitControl ParentSplitControl
        {
            get
            {
                var parent = this.ParentSplitPanel;
                var splitCtrl = (parent != null) ? parent.Parent as XIDESplitControl : null;
                return splitCtrl;
            }
        }


        public virtual bool PanelAllCollapsed { get; private set; }
        public virtual new bool Panel1Collapsed
        {
            get { return base.Panel1Collapsed; }
            set
            {
                if (base.Panel1Collapsed != value) Console.WriteLine(string.Format("Panel1Collapsed [{0}]: {1} > {2}", this.GetHashCode(), base.Panel1Collapsed, value));
                PanelAllCollapsed = this.Panel2Collapsed && value;
                base.Panel1Collapsed = value;
            }
        }
        public virtual new bool Panel2Collapsed
        {
            get { return base.Panel2Collapsed; }
            set
            {
                if (base.Panel2Collapsed != value) Console.WriteLine(string.Format("Panel2Collapsed [{0}]: {1} > {2}", this.GetHashCode(), base.Panel2Collapsed, value));
                PanelAllCollapsed = this.Panel1Collapsed && value;
                base.Panel2Collapsed = value;
            }
        }
        //public new System.Windows.Forms.Control Parent
        //{
        //    get { return base.Parent; }
        //    set
        //    {
        //        if (base.Parent == value) return;

        //        var old = base.Parent;
        //        if (old != null) old.Controls.Remove(this);
        //        if (old != null && old.Controls.Contains(this))
        //            throw new Exception(string.Format("当代码设置 Parent 移除 IDESplitControl 后, Parent 的 Controls 依然包含此 IDESplitControl (这可能是 .Net 底层 WinForm 的 BUG) : \r\n    Parent = {0} \r\n    IDESplitControl = {1}", old, this));

        //        base.Parent = value;
        //    }
        //}




        public XIDETabGroup FindGroup()
        {
            var group1 = FindGroup(this.Panel1);
            if (group1 != null) return group1;

            var group2 = FindGroup(this.Panel2);
            if (group2 != null) return group2;

            return null;
        }
        private static XIDETabGroup FindGroup(System.Windows.Forms.Control ctrl)
        {
            var ctrls1 = ctrl.Controls;
            if (ctrls1.Count <= 0) return null;

            foreach (var ctrl2 in ctrls1)
            {
                if (ctrl2 is XIDETabGroup) { return (XIDETabGroup)ctrl2; }
                if (ctrl2 is XIDESplitControl)
                {
                    var splitCtrl = (XIDESplitControl)ctrl2;
                    var group = splitCtrl.FindGroup();
                    if (group != null) return group;
                }
            }
            return null;
        }


        public void ResetLayout()
        {
            var ctrls1 = new List<System.Windows.Forms.Control>();
            var ctrls2 = new List<System.Windows.Forms.Control>();
            foreach (System.Windows.Forms.Control ctrl in this.Panel1.Controls) { ctrls1.Add(ctrl); }
            foreach (System.Windows.Forms.Control ctrl in this.Panel2.Controls) { ctrls2.Add(ctrl); }

            foreach (var ctrl in ctrls1)
            {
                if (ctrl.IsDisposed) { ctrl.Parent = null; this.Panel1.Controls.Remove(ctrl); }     //理论上这是不可能出现的 判断条件
                if (ctrl.Parent != this.Panel1) { this.Panel1.Controls.Remove(ctrl); }              //理论上这是不可能出现的 判断条件
                if (ctrl is XIDEPanelCenter) { ((XIDEPanelCenter)ctrl).ResetLayout(); }
                if (ctrl is XIDESplitControl) { ((XIDESplitControl)ctrl).ResetLayout(); }
            }

            foreach (var ctrl in ctrls2)
            {
                if (ctrl.IsDisposed) { ctrl.Parent = null; this.Panel2.Controls.Remove(ctrl); }     //理论上这是不可能出现的 判断条件
                if (ctrl.Parent != this.Panel2) { this.Panel2.Controls.Remove(ctrl); }              //理论上这是不可能出现的 判断条件
                if (ctrl is XIDEPanelCenter) { ((XIDEPanelCenter)ctrl).ResetLayout(); }
                if (ctrl is XIDESplitControl) { ((XIDESplitControl)ctrl).ResetLayout(); }
            }

            this.DoLayout();
        }

        protected bool m_DoLayout = false;
        public void DoLayout()
        {
            if (m_DoLayout) return;

            try
            {
                m_DoLayout = true;
                //Console.WriteLine("IDESplitControl.DoLayout() " + DateTime.Now.ToString("HH:mm:ss fff"));
                if (this.Disposing || this.IsDisposed || this.IDEPanel == null) return;

                bool hide1, hide2;
                var ctrl1 = this.IDEPanel.FindTabGroupOrSplitControl(this.Panel1, out hide1);
                var ctrl2 = this.IDEPanel.FindTabGroupOrSplitControl(this.Panel2, out hide2);

                #region  处理 已关闭的 部分

                if ((ctrl1 == null && ctrl2 != null) || (ctrl2 == null && ctrl1 != null))
                {
                    #region  执行合并

                    var parent = this.Parent;
                    if (parent != null) parent.SuspendLayout();

                    var ctrl = ctrl1 ?? ctrl2;
                    ctrl.Parent = parent; //(parent is IDEPanel) ? ((IDEPanel) parent).CenterPanel : parent;
                    this.Dispose();
                    Console.WriteLine("IDESplitControl.Dispose()");

                    if (parent != null) parent.ResumeLayout();
                    return;

                    #endregion
                }

                if (ctrl1 != null && ctrl2 != null)
                {
                    #region  执行折叠

                    base.SuspendLayout();
                    this.Panel1Collapsed = hide1;
                    this.Panel2Collapsed = hide2;
                    base.ResumeLayout(true);

                    #endregion
                }

                #endregion

            }
            finally { m_DoLayout = false; }
        }


        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            //e.Graphics.Clear(Color.Tomato);
        }

        public virtual new void Dispose()
        {
            this.ParentChanged -= IDESplitControlParentChanged;
            this.Panel1.ControlAdded -= IDESplitControlPanelControlAdded;
            this.Panel2.ControlAdded -= IDESplitControlPanelControlAdded;
            this.Panel1.ControlRemoved -= IDESplitControlPanelControlRemoved;
            this.Panel2.ControlRemoved -= IDESplitControlPanelControlRemoved;

            var ctrls1 = this.Panel1.Controls;
            var ctrls2 = this.Panel1.Controls;
            if (ctrls1.Count >= 1) ctrls1.Clear();
            if (ctrls2.Count >= 1) ctrls2.Clear();

            this.Parent = null;
            this.m_IDEPanel = null;
            base.Dispose();
        }



        public static bool SplitPanelExpand(XIDEPanel idePanel, InkFx.WinControl.SplitterPanel panel)
        {
            if (panel == null) return false;
            var ctrls = panel.Controls;
            var ctrl = (ctrls.Count >= 1 ? ctrls[0] : null) ?? idePanel.FindTabGroup(panel);
            if (ctrl is XIDETabGroup) return ((XIDETabGroup)ctrl).State == DTGS.Expand;
            if (ctrl is XIDESplitControl) return SplitControlExpand(idePanel, (XIDESplitControl)ctrl);
            return false;
        }
        public static bool SplitControlExpand(XIDEPanel idePanel, XIDESplitControl control)
        {
            if (control == null) return false;
            var riveted1 = SplitPanelExpand(idePanel, control.Panel1);
            if (riveted1) return true;
            var riveted2 = SplitPanelExpand(idePanel, control.Panel2);
            if (riveted2) return true;
            return false;
        }
    }
}
